package ar.edu.utn.frba.dds.tp.code.adapter;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import ar.edu.utn.frba.dds.tp.code.Asientos.AsientoDeVuelo;
import ar.edu.utn.frba.dds.tp.code.Asientos.EstadoAsiento;
import ar.edu.utn.frba.dds.tp.code.lugares.Lugar;
import ar.edu.utn.frba.dds.tp.code.transacciones.TipoTransaccion;
import ar.edu.utn.frba.dds.tp.code.transacciones.Transaccion;
import ar.edu.utn.frba.dds.tp.code.usuarios.Usuario;
import ar.edu.utn.frba.dds.tp.code.usuarios.UsuarioStandard;
import ar.edu.utn.frba.dds.tp.code.vuelos.Aerolinea;
import ar.edu.utn.frba.dds.tp.code.vuelos.Busqueda;
import ar.edu.utn.frba.dds.tp.code.vuelos.ExistingReservationException;
import ar.edu.utn.frba.dds.tp.code.vuelos.TransactionCouldntSucceedException;
import ar.edu.utn.frba.dds.tp.code.vuelos.Vuelo;

import com.oceanic.AerolineaOceanic;
import com.oceanic.AsientoDTO;

public class OceanicAdapter extends Aerolinea {
	
	private static OceanicAdapter instance;
	private AerolineaOceanic aerolineaOceanic = AerolineaOceanic.getInstance();
	private OceanicConversor conversor = new OceanicConversor();

	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	//+++ Oceanic ++++++++++++++++++++++++++++++++++++++++++++++++
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	
	public static OceanicAdapter getInstance() {
		if (instance == null)
			instance = new OceanicAdapter();
		return instance;
	}

	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	// +++ Constructors +++++++++++++++++++++++++++++++++++++++++++
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	
	public OceanicAdapter() {
		super();
		this.setName("Oceanic");
	}
	
	private OceanicAdapter(Aerolinea aero) {
		super (aero);
		this.setName("Oceanic");
		
	}
	
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	// +++ methods ++++++++++++++++++++++++++++++++++++++++++++++++
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	
	@Override
	public void comprarAsiento(AsientoDeVuelo asiento, Usuario comprador) {
		String codigoVuelo = asiento.getCodigoDeVuelo();
		int numeroDeAsiento = asiento.getNumeroDeAsiento();
		String dni = Integer.toString(comprador.getDni());
		if(aerolineaOceanic.comprarSiHayDisponibilidad(dni, codigoVuelo, numeroDeAsiento)){
			asiento.fuisteComprado();
			super.registrarTransaccion(new Transaccion(asiento, comprador, TipoTransaccion.COMPRA));
		}
		else{
			throw new TransactionCouldntSucceedException("el asiento no se encuentra a la venta"); 
		}
	}
	
	@Override
	public List<Vuelo> vuelosDisponibles(Busqueda busqueda) {
		List<AsientoDTO> asientosOceanic = busqueda.getDestino().disponiblesDe(this,busqueda);
		ArrayList<Vuelo> vuelos = new ArrayList<Vuelo>();
		
		for (AsientoDTO asientoDTO : asientosOceanic) {
			AsientoDeVuelo asiento = conversor.convertirAsiento(asientoDTO);
			this.ponerEnVuelo(asiento, vuelos);
		}
				
		return vuelos;
	}

	SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
	
	public List<AsientoDTO> realizarBusquedaCon(Lugar lugar,Busqueda busqueda) {
		String origen = this.conversor.fromLugarToLugarOceanic(busqueda.getOrigen().getLugar());
		String destino = this.conversor.fromLugarToLugarOceanic(busqueda.getDestino().getLugar());
		String fechaDeSalida = format.format(busqueda.getFechaSalida());
		return this.aerolineaOceanic.asientosDisponiblesParaOrigenYDestino(origen, destino, fechaDeSalida);
	}

	public List<AsientoDTO> realizarBusquedaSin(Busqueda busqueda) {
		String origen = this.conversor.fromLugarToLugarOceanic(busqueda.getOrigen().getLugar());
		String fechaDeSalida = format.format(busqueda.getFechaSalida());
		return this.aerolineaOceanic.asientosDisponiblesParaOrigen(origen, fechaDeSalida);
	}
	
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	//+++ Reservas +++++++++++++++++++++++++++++++++++++++++++++++
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	
	@Override
	public void reservarAsiento(AsientoDeVuelo asiento, UsuarioStandard reservante){
		String codigoVuelo = asiento.getCodigoDeVuelo();
		String dni = Integer.toString(reservante.getDni());
		int numeroDeAsiento = asiento.getNumeroDeAsiento();
		if(!aerolineaOceanic.estaComprado(codigoVuelo, numeroDeAsiento)){
			if(!aerolineaOceanic.estaReservado(codigoVuelo, numeroDeAsiento)){
				if(aerolineaOceanic.reservar(dni, codigoVuelo, numeroDeAsiento)){
					asiento.setEstado(EstadoAsiento.RESERVADO);
					this.update(asiento);	
				}
				else
					throw new TransactionCouldntSucceedException("el asiento no se encuentra disponible para reserva");
			}
			else
				throw new ExistingReservationException();
			super.registrarTransaccion(new Transaccion(asiento, reservante, TipoTransaccion.RESERVA));
		}
		else{
			throw new TransactionCouldntSucceedException("el asiento se encuentra comprado"); 
		}
	}
	
	public void expiroReserva(AsientoDTO asientoDTO){  // asientoDTO como los maneja oceanic 
		
		AsientoDeVuelo asiento = conversor.convertirAsiento(asientoDTO);
		transferirReserva(asiento);
	}


	@Override
	public AbstractConversor getConversor() {
		return this.conversor;
	}
}
